package com.cya.lotterysystem.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.cya.lotterysystem.common.errcode.ServiceErrorCodeConstans;
import com.cya.lotterysystem.common.exception.ServiceException;
import com.cya.lotterysystem.common.utils.JWTUtil;
import com.cya.lotterysystem.common.utils.RegexUtil;
import com.cya.lotterysystem.controller.param.ShortMessageLoginParam;
import com.cya.lotterysystem.controller.param.UserLoginParam;
import com.cya.lotterysystem.controller.param.UserPasswordLoginParam;
import com.cya.lotterysystem.controller.param.UserRegisterParam;
import com.cya.lotterysystem.dao.dataobject.Encrypt;
import com.cya.lotterysystem.dao.dataobject.UserDo;
import com.cya.lotterysystem.dao.mapper.UserMapper;
import com.cya.lotterysystem.service.UserService;
import com.cya.lotterysystem.service.VerificationCodeService;
import com.cya.lotterysystem.service.dto.UserDTO;
import com.cya.lotterysystem.service.dto.UserLoginDTO;
import com.cya.lotterysystem.service.dto.UserRegisterDTO;
import com.cya.lotterysystem.service.enums.UserIdentityEnum;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author ：陈奕安（3048279304@qq.com）
 * @date ：Created in 2025/10/28 16:41
 * @description：
 * @modified By：
 * @version:
 */

@Service
public class UserServiceImpl implements UserService {
    private final static Logger logger= LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;


    @Autowired
    private VerificationCodeService verificationCodeService;



    @Override
    public UserRegisterDTO register(UserRegisterParam param) {

        //校验注册信息
checkRegisterInfo(param);
//        加密私密数据（构造dao层请求）
        UserDo  userDo=new UserDo();
        userDo.setUserName(param.getName());
        userDo.setEmail(param.getMail());
        userDo.setPhoneNumber(new Encrypt(param.getPhoneNumber()));
        userDo.setIdentity(param.getIdentity());
        if (StringUtils.hasText(param.getPassword())){
            userDo.setPassword(DigestUtil.sha256Hex(param.getPassword()));
        }

//        保存数据
userMapper.insert(userDo);
//        构造返回
        UserRegisterDTO userRegisterDTO=new UserRegisterDTO();
        userRegisterDTO.setUserId(userDo.getId());
        return userRegisterDTO;
    }

    @Override
    public UserLoginDTO login(UserLoginParam param) {
        UserLoginDTO userLoginDTO;
//        类型检查与转换
        if(param instanceof UserPasswordLoginParam loginParam)
        {
//            密码登录
     return    userLoginDTO=loginByUserPassword(loginParam);
        }
        else if (param instanceof ShortMessageLoginParam loginParam){
         return    userLoginDTO=loginByShortMessage(loginParam);
        }else {
            throw new ServiceException(ServiceErrorCodeConstans.LOGIN_INFO_NOT_EXIST);

        }


    }

    @Override
    public List<UserDTO> findUserInfo(UserIdentityEnum identity) {

        String identityString = null == identity ? null : identity.name();


//        查表
        List<UserDo> userDOList=userMapper.selectUserInfoByIdentity(identityString);

//        转换类型
        List<UserDTO> userDTOList=userDOList.stream()
                .map(userDO -> {
                    UserDTO userDTO=new UserDTO();
                    userDTO.setUserId(userDO.getId());
                    userDTO.setUserName(userDO.getUserName());
                    userDTO.setEmail(userDO.getEmail());
                    userDTO.setPhoneNumber(userDO.getPhoneNumber().getValue());
                    userDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity()));
                    return userDTO;
                }).collect(Collectors.toList());
        return userDTOList;
    }

    /**
     * 验证码登录
     * @param loginParam
     * @return
     */
    private UserLoginDTO loginByShortMessage(ShortMessageLoginParam loginParam) {

        if (!RegexUtil.checkMobile(loginParam.getLoginMobile())) {
            throw new ServiceException(ServiceErrorCodeConstans.PHONE_ERRROR);

        }
//        获取用户数据
//        数据库数据返回类型
        UserDo userDo=userMapper.selecyByPhoneNumber(new Encrypt(loginParam.getLoginMobile()));
        if (userDo==null){
            throw new ServiceException(ServiceErrorCodeConstans.USER_INFO_NOT_EXIST);
        }
        else if (StringUtils.hasText(loginParam.getMandatoryIdentity())
        && !loginParam.getMandatoryIdentity()
                .equalsIgnoreCase(userDo.getIdentity())){
            throw new ServiceException(ServiceErrorCodeConstans.IDENTITY_ERROR);

        }
//        校验验证码
      String code=  verificationCodeService.getVerificationCode(loginParam.getLoginMobile());
        if (!loginParam.getVerificationCode().equals(code)){
            throw new ServiceException(ServiceErrorCodeConstans.VERIFICATION_ERROR);
        }
//        返回值
        Map<String,Object> claim=new HashMap<>();
        claim.put("id",userDo.getId());
        claim.put("identity",userDo.getIdentity());
        String token = JWTUtil.genJwt(claim);
        UserLoginDTO userLoginDTO=new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.forName(userDo.getIdentity()));
        return userLoginDTO;

    }

    /**
     * 密码登录
     * @param loginParam
     * @return
     */
    private UserLoginDTO loginByUserPassword(UserPasswordLoginParam loginParam) {
//        用于查询数据表返回的数据的对象

        UserDo userDo=null;
//       判断是手机还是邮箱

        if (RegexUtil.checkMail(loginParam.getLoginName())){
//邮箱登录
            userDo=userMapper.selectByMail(loginParam.getLoginName());
        }else if (RegexUtil.checkMobile(loginParam.getLoginName())){
//            手机号错误
            userDo=userMapper.selecyByPhoneNumber(new Encrypt(loginParam.getLoginName()));
        }else {
            throw new ServiceException(ServiceErrorCodeConstans.LOGIN_NOT_EXIST);
        }
        if (userDo==null){
            throw new ServiceException(ServiceErrorCodeConstans.USER_INFO_NOT_EXIST);
        } else if (StringUtils.hasText(loginParam.getMandatoryIdentity())
                &&! userDo.getIdentity().equalsIgnoreCase(loginParam.getMandatoryIdentity())) {

//            强制身份校验不通过
            throw new ServiceException(ServiceErrorCodeConstans.IDENTITY_ERROR);
        }else if (!DigestUtil.sha256Hex(loginParam.getPassword()).equals(userDo.getPassword())){
//            校验密码不通过
            throw new ServiceException(ServiceErrorCodeConstans.PASSWORD_ERROR);
        }
//        返回值
        Map<String,Object> claim=new HashMap<>();
        claim.put("id",userDo.getId());
        claim.put("identity",userDo.getIdentity());
        String token = JWTUtil.genJwt(claim);
        UserLoginDTO userLoginDTO=new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.forName(userDo.getIdentity()));
        return userLoginDTO;
    }

    private void checkRegisterInfo(UserRegisterParam param) {
        logger.info("接收到的参数：{}", param);
        logger.info("phoneNumber 字段值：{}", param.getPhoneNumber());
        if (null==param){
            throw new ServiceException(ServiceErrorCodeConstans.REGISTER_INFO_EMPTY);
        }
//        校验邮箱格式 xxx@xxx.xxx
if (!RegexUtil.checkMail(param.getMail())){
    throw new ServiceException(ServiceErrorCodeConstans.MAIL_ERROR);
}
//        校验手机号格式
        if (!RegexUtil.checkMobile(param.getPhoneNumber())){
            throw new ServiceException(ServiceErrorCodeConstans.PHONE_ERRROR);
        }

//检验身份信息
        if (UserIdentityEnum.forName(param.getIdentity())==null){
            throw new ServiceException(ServiceErrorCodeConstans.IDENTITY_EMPTY);
        }


//        校验管理员密码必填
                if (param.getIdentity().equalsIgnoreCase(UserIdentityEnum.ADMIN.name())
                &&!StringUtils.hasText(param.getPassword())){
                    throw new ServiceException(ServiceErrorCodeConstans.PASSWORD_IS_EMPTY);
                }

                //        校验密码长度
                if (StringUtils.hasText(param.getPassword())
                &&!RegexUtil.checkPassword(param.getPassword())){
                    throw new ServiceException(ServiceErrorCodeConstans.PASSWORD_ERROR);
                }
//        校验邮箱是否被使用
        if (checkMailUsed(param.getMail())){
            throw new ServiceException(ServiceErrorCodeConstans.MAIL_USED);
        }

        if (checkPhoneNumber(param.getPhoneNumber())){
            throw new ServiceException(ServiceErrorCodeConstans.PHONE_USED);
        }
    }

    private boolean checkPhoneNumber(String phoneNumber) {
        int count=userMapper.countByPhone(new Encrypt(phoneNumber));
        return count>0;
    }

    private boolean checkMailUsed(String mail) {
        int count=userMapper.countByMail(mail);
        return count>0;
    }
}